# MINIMAL_FMTS
set(MINIMAL_FMTS
garmin.cc
- garmin_device_xml.cc
garmin_tables.cc
geo.cc
gpx.cc
filter_vecs.h
format.h
formspec.h
- garmin_device_xml.h
garmin_fit.h
garmin_fs.h
garmin_gpi.h
--- /dev/null
+/*
+ Parse 'GarminDevice.xml' on a Garmin mass storage device (e.g. Zumo,
+ Nuvi, Colorado, etc. and return key device info.
+
+ Copyright (C) 2008 Robert Lipe, robertlipe+source@gpsbabel.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ */
+
+// References:
+// http://developer.garmin.com/web-device/garmin-mass-storage-mode-devices/
+// http://developer.garmin.com/schemas/device/v2/
+
+
+#include "defs.h"
+#include "garmin_device_xml.h"
+#include "xmlgeneric.h"
+#include <QXmlStreamAttributes>
+#include <QFile>
+#include <cstdio>
+
+#define MYNAME "whatever"
+
+static gdx_info* my_gdx_info;
+static int type;
+static char* mountpoint, *base, *path, *ext;
+static xg_callback device_s, id_s, path_s, ext_s, base_s, dir_s;
+jmp_buf gdx_jmp_buf;
+
+static void type_s(xg_string args, const QXmlStreamAttributes*)
+{
+ type = args.compare(u"GPSData");
+}
+
+void device_s(xg_string args, const QXmlStreamAttributes*)
+{
+ if (my_gdx_info) {
+ fatal(MYNAME ": More than one device type found in file.\n");
+ }
+ my_gdx_info = (gdx_info*) xcalloc(sizeof *my_gdx_info, 1);
+ my_gdx_info->device_desc = xstrdup(args);
+}
+
+void id_s(xg_string args, const QXmlStreamAttributes*)
+{
+ my_gdx_info->device_id = xstrdup(args);
+}
+
+void path_s(xg_string args, const QXmlStreamAttributes*)
+{
+ path = xstrdup(args);
+}
+
+void ext_s(xg_string args, const QXmlStreamAttributes*)
+{
+ ext = xstrdup(args);
+}
+
+void base_s(xg_string args, const QXmlStreamAttributes*)
+{
+ base = xstrdup(args);
+}
+
+void dir_s(xg_string args, const QXmlStreamAttributes*)
+{
+ if (type) {
+ return;
+ }
+ if (args == "OutputFromUnit") {
+ xasprintf(&my_gdx_info->from_device.path, "%s%c%s",
+ mountpoint, GB_PATHSEP, path);
+ my_gdx_info->from_device.basename = xstrdup(base);
+ my_gdx_info->from_device.extension = xstrdup(ext);
+ xasprintf(&my_gdx_info->from_device.canon, "%s/%s.%s",
+ my_gdx_info->from_device.path,
+ my_gdx_info->from_device.basename,
+ my_gdx_info->from_device.extension);
+ } else if (args == "InputToUnit") {
+ xasprintf(&my_gdx_info->to_device.path, "%s%c%s",
+ mountpoint, GB_PATHSEP, path);
+ my_gdx_info->to_device.basename = xstrdup(base);
+ my_gdx_info->to_device.extension = xstrdup(ext);
+ } else {
+ fatal(MYNAME ":Unknown direction '%s'\n", qPrintable(args));
+ }
+
+ if (base) {
+ xfree(base) ;
+ }
+ base = nullptr;
+
+ if (ext) {
+ xfree(ext) ;
+ }
+ ext = nullptr;
+
+ if (path) {
+ xfree(path) ;
+ }
+ path = nullptr;
+}
+
+static QList<xg_tag_mapping> gdx_map = {
+ { device_s, cb_cdata, "/Device/Model/Description" },
+ { id_s, cb_cdata, "/Device/Id" },
+ { path_s, cb_cdata, "/Device/MassStorageMode/DataType/File/Location/Path" },
+ { type_s, cb_cdata, "/Device/MassStorageMode/DataType/Name" },
+ { ext_s, cb_cdata, "/Device/MassStorageMode/DataType/File/Location/FileExtension" },
+ { base_s, cb_cdata, "/Device/MassStorageMode/DataType/File/Location/BaseName" },
+ { dir_s, cb_cdata, "/Device/MassStorageMode/DataType/File/TransferDirection" },
+};
+
+const gdx_info*
+gdx_read(const char* fname)
+{
+ // Test file open-able before gb_open gets a chance to fatal().
+ if (QFile(fname).open(QIODevice::ReadOnly)) {
+ xml_init(fname, gdx_map, nullptr);
+ xml_read();
+ xml_deinit();
+ }
+
+ return my_gdx_info;
+}
+
+
+// Look for the Device in the incoming NULL-terminated list of directories
+const gdx_info*
+gdx_find_file(char** dirlist)
+{
+ while (dirlist && *dirlist) {
+ char* tbuf;
+ xasprintf(&tbuf, "%s/%s", *dirlist, "/Garmin/GarminDevice.xml");
+ mountpoint = *dirlist;
+ const gdx_info* gdx = gdx_read(tbuf);
+ xfree(tbuf);
+ if (gdx) {
+ longjmp(gdx_jmp_buf, 1);
+ }
+ dirlist++;
+ }
+ return nullptr;
+}
+
+const gdx_info*
+gdx_get_info()
+{
+ return my_gdx_info;
+}
--- /dev/null
+/*
+ Parse 'GarminDevice.xml' on a Garmin mass storage device (e.g. Zumo,
+ Nuvi, Colorado, etc. and return key device info.
+
+ Copyright (C) 2008-2014 Robert Lipe
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ */
+#ifndef GARMIN_DEVICE_XML_H_
+#define GARMIN_DEVICE_XML_H_
+
+/*
+ * Describes a file on the unit.
+ */
+struct gdx_file {
+ char* path;
+ char* basename;
+ char* extension;
+ char* canon; // full name, when applicable.
+};
+
+/*
+ * The interesting traits of this device.
+ */
+struct gdx_info {
+ const char* device_desc;
+ const char* device_id;
+ const char* device_mounted_path; // Not from the file; about the file.
+ gdx_file from_device;
+ gdx_file to_device;
+// gdx_file geocache_logs;
+};
+
+const gdx_info* gdx_read(const char* fname);
+const gdx_info* gdx_get_info();
+const gdx_info* gdx_find_file(char** dirlist);
+
+// This is so gross. By the time we know it's not a USB device
+// and could be one of our devices, we're so deep into the callstack
+// that can't back out gracefully without bludgeoning most of the
+// (Mac|Lin|Win) x (USB|Serial) matrix. Since we don't *really* want
+// to progress any further, we just longjump back to the caller...
+#include <csetjmp>
+extern jmp_buf gdx_jmp_buf;
+
+#endif // GARMIN_DEVICE_XML_H_
#include <cassert> // for assert
#include <climits> // for INT_MAX
#include <cmath> // for atan2, floor, sqrt
-#include <csetjmp> // for setjmp
#include <cstdio> // for fprintf, fflush, snprintf, snprintf
#include <cstdlib> // for strtol
#include <cstring> // for memcpy, strlen, strncpy, strchr
#include <ctime> // for time_t
#include <QByteArray> // for QByteArray
-#include <QChar> // for QChar
#include <QRegularExpression> // for QRegularExpression
#include <QString> // for QString
#include <QTextCodec> // for QTextCodec
#include <QtGlobal> // for qPrintable, foreach
#include "defs.h"
-#include "format.h" // for Format
#include "formspec.h" // for FormatSpecificDataList
-#include "garmin_device_xml.h" // for gdx_get_info, gdx_info, gdx_file, gdx_jmp_buf
#include "garmin_fs.h" // for garmin_fs_garmin_after_read, garmin_fs_garmin_before_write
#include "garmin_tables.h" // for gt_find_icon_number_from_desc, PCX, gt_find_desc_from_icon_number
#include "geocache.h" // for Geocache, Geocache::type_t, Geocache...
#include "jeeps/gpsserial.h" // for DEFAULT_BAUD
#include "jeeps/gpsutil.h" // for GPS_User, GPS_Enable_Diagnose, GPS_E...
#include "src/core/datetime.h" // for DateTime
-#include "vecs.h" // for Vecs
#define MYNAME "GARMIN"
static int receiver_must_upper = 1;
static QTextCodec* codec{nullptr};
-static Vecs::fmtinfo_t gpx_vec;
-
#define MILITANT_VALID_WAYPT_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
/* Technically, even this is a little loose as spaces aren't allowed */
static void
rd_init(const QString& fname)
{
- if (setjmp(gdx_jmp_buf)) {
- const gdx_info* gi = gdx_get_info();
- // FIXME: dynamic not implemented.
- gpx_vec = Vecs::Instance().find_vec("gpx");
- Vecs::prepare_format(gpx_vec);
- gpx_vec->rd_init(gi->from_device.canon);
- } else {
- gpx_vec = Vecs::fmtinfo_t();
- rw_init(fname);
- }
+ rw_init(fname);
}
static void
static void
data_read()
{
- if (gpx_vec) {
- gpx_vec->read();
- return;
- }
-
if (poweroff) {
return;
}
+++ /dev/null
-/*
- Parse 'GarminDevice.xml' on a Garmin mass storage device (e.g. Zumo,
- Nuvi, Colorado, etc. and return key device info.
-
- Copyright (C) 2008 Robert Lipe, robertlipe+source@gpsbabel.org
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
- */
-
-// References:
-// http://developer.garmin.com/web-device/garmin-mass-storage-mode-devices/
-// http://developer.garmin.com/schemas/device/v2/
-
-
-#include "defs.h"
-#include "garmin_device_xml.h"
-#include "xmlgeneric.h"
-#include <QXmlStreamAttributes>
-#include <QFile>
-#include <cstdio>
-
-#define MYNAME "whatever"
-
-static gdx_info* my_gdx_info;
-static int type;
-static char* mountpoint, *base, *path, *ext;
-static xg_callback device_s, id_s, path_s, ext_s, base_s, dir_s;
-jmp_buf gdx_jmp_buf;
-
-static void type_s(xg_string args, const QXmlStreamAttributes*)
-{
- type = args.compare(u"GPSData");
-}
-
-void device_s(xg_string args, const QXmlStreamAttributes*)
-{
- if (my_gdx_info) {
- fatal(MYNAME ": More than one device type found in file.\n");
- }
- my_gdx_info = (gdx_info*) xcalloc(sizeof *my_gdx_info, 1);
- my_gdx_info->device_desc = xstrdup(args);
-}
-
-void id_s(xg_string args, const QXmlStreamAttributes*)
-{
- my_gdx_info->device_id = xstrdup(args);
-}
-
-void path_s(xg_string args, const QXmlStreamAttributes*)
-{
- path = xstrdup(args);
-}
-
-void ext_s(xg_string args, const QXmlStreamAttributes*)
-{
- ext = xstrdup(args);
-}
-
-void base_s(xg_string args, const QXmlStreamAttributes*)
-{
- base = xstrdup(args);
-}
-
-void dir_s(xg_string args, const QXmlStreamAttributes*)
-{
- if (type) {
- return;
- }
- if (args == "OutputFromUnit") {
- xasprintf(&my_gdx_info->from_device.path, "%s%c%s",
- mountpoint, GB_PATHSEP, path);
- my_gdx_info->from_device.basename = xstrdup(base);
- my_gdx_info->from_device.extension = xstrdup(ext);
- xasprintf(&my_gdx_info->from_device.canon, "%s/%s.%s",
- my_gdx_info->from_device.path,
- my_gdx_info->from_device.basename,
- my_gdx_info->from_device.extension);
- } else if (args == "InputToUnit") {
- xasprintf(&my_gdx_info->to_device.path, "%s%c%s",
- mountpoint, GB_PATHSEP, path);
- my_gdx_info->to_device.basename = xstrdup(base);
- my_gdx_info->to_device.extension = xstrdup(ext);
- } else {
- fatal(MYNAME ":Unknown direction '%s'\n", qPrintable(args));
- }
-
- if (base) {
- xfree(base) ;
- }
- base = nullptr;
-
- if (ext) {
- xfree(ext) ;
- }
- ext = nullptr;
-
- if (path) {
- xfree(path) ;
- }
- path = nullptr;
-}
-
-static QList<xg_tag_mapping> gdx_map = {
- { device_s, cb_cdata, "/Device/Model/Description" },
- { id_s, cb_cdata, "/Device/Id" },
- { path_s, cb_cdata, "/Device/MassStorageMode/DataType/File/Location/Path" },
- { type_s, cb_cdata, "/Device/MassStorageMode/DataType/Name" },
- { ext_s, cb_cdata, "/Device/MassStorageMode/DataType/File/Location/FileExtension" },
- { base_s, cb_cdata, "/Device/MassStorageMode/DataType/File/Location/BaseName" },
- { dir_s, cb_cdata, "/Device/MassStorageMode/DataType/File/TransferDirection" },
-};
-
-const gdx_info*
-gdx_read(const char* fname)
-{
- // Test file open-able before gb_open gets a chance to fatal().
- if (QFile(fname).open(QIODevice::ReadOnly)) {
- xml_init(fname, gdx_map, nullptr);
- xml_read();
- xml_deinit();
- }
-
- return my_gdx_info;
-}
-
-
-// Look for the Device in the incoming NULL-terminated list of directories
-const gdx_info*
-gdx_find_file(char** dirlist)
-{
- while (dirlist && *dirlist) {
- char* tbuf;
- xasprintf(&tbuf, "%s/%s", *dirlist, "/Garmin/GarminDevice.xml");
- mountpoint = *dirlist;
- const gdx_info* gdx = gdx_read(tbuf);
- xfree(tbuf);
- if (gdx) {
- longjmp(gdx_jmp_buf, 1);
- }
- dirlist++;
- }
- return nullptr;
-}
-
-const gdx_info*
-gdx_get_info()
-{
- return my_gdx_info;
-}
+++ /dev/null
-/*
- Parse 'GarminDevice.xml' on a Garmin mass storage device (e.g. Zumo,
- Nuvi, Colorado, etc. and return key device info.
-
- Copyright (C) 2008-2014 Robert Lipe
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
- */
-#ifndef GARMIN_DEVICE_XML_H_
-#define GARMIN_DEVICE_XML_H_
-
-/*
- * Describes a file on the unit.
- */
-struct gdx_file {
- char* path;
- char* basename;
- char* extension;
- char* canon; // full name, when applicable.
-};
-
-/*
- * The interesting traits of this device.
- */
-struct gdx_info {
- const char* device_desc;
- const char* device_id;
- const char* device_mounted_path; // Not from the file; about the file.
- gdx_file from_device;
- gdx_file to_device;
-// gdx_file geocache_logs;
-};
-
-const gdx_info* gdx_read(const char* fname);
-const gdx_info* gdx_get_info();
-const gdx_info* gdx_find_file(char** dirlist);
-
-// This is so gross. By the time we know it's not a USB device
-// and could be one of our devices, we're so deep into the callstack
-// that can't back out gracefully without bludgeoning most of the
-// (Mac|Lin|Win) x (USB|Serial) matrix. Since we don't *really* want
-// to progress any further, we just longjump back to the caller...
-#include <csetjmp>
-extern jmp_buf gdx_jmp_buf;
-
-#endif // GARMIN_DEVICE_XML_H_
#include "jeeps/garminusb.h"
#include "jeeps/gpsdevice.h"
#include "jeeps/gpsusbcommon.h"
-#include "garmin_device_xml.h"
#define GARMIN_VID 0x91e
static bool libusb_successfully_initialized{false};
static libusb_device_handle* udev{nullptr};
static int garmin_usb_scan(libusb_unit_data*, int);
-static const gdx_info* gdx;
static int gusb_libusb_get(garmin_usb_packet* ibuf, size_t sz);
static int gusb_libusb_get_bulk(garmin_usb_packet* ibuf, size_t sz);
0
};
-#if __linux__
-static
-char** os_get_garmin_mountpoints()
-{
- // Hacked for testing.
- return nullptr;
-}
-#elif __APPLE__
-// In fantasy land, we'd query iokit for enumerated devices of the Garmin
-// vendor ID and match that against the mounted device table. In practical
-// matters, that's crazy complex and this is where the devices seems to always
-// get mounted...
-char** os_get_garmin_mountpoints()
-{
- char** dlist = (char**) xcalloc(2, sizeof *dlist);
- dlist[0] = xstrdup("/Volumes/GARMIN");
- dlist[1] = nullptr;
- return dlist;
-}
-#else
-char** os_get_garmin_mountpoints()
-{
- return nullptr;
-}
-#endif
-
-
static int
gusb_libusb_send(const garmin_usb_packet* opkt, size_t sz)
{
}
if (0 == found_devices) {
- /* It's time for Plan B. The user told us to use
- * Garmin Protocol in device "usb:" but it's possible
- * that they're talking to one of the dozens of models
- * that is wants to read and write GPX files on a
- * mounted drive. Try that now.
- */
- char** dlist = os_get_garmin_mountpoints();
- gdx = gdx_find_file(dlist);
- if (gdx != nullptr) {
- return 1;
- }
- /* Plan C. */
fatal("Found no Garmin USB devices.\n");
} else if (req_unit_number >= found_devices) {
fatal("usb unit number(%d) too high.\n"
#include <setupapi.h>
#include <winioctl.h>
-#include "garmin_device_xml.h"
#include "jeeps/garminusb.h"
#include "jeeps/gps.h"
#include "jeeps/gpsapp.h"
static HANDLE usb_handle = INVALID_HANDLE_VALUE;
static int usb_tx_packet_size ;
-static const gdx_info* gdx;
static int
gusb_win_close(gpsdevh* /* handle */, bool /* exit_lib */)
return usb_handle;
}
-
-static char** get_garmin_mountpoints(void)
-{
-#define BUFSIZE 512
- char szTemp[MAX_PATH];
- char* p = szTemp;
- char** dlist = (char **) xmalloc(sizeof(*dlist));
-
- dlist[0] = NULL;
-
- if (GetLogicalDriveStringsA(BUFSIZE-1, szTemp)) {
- int i = 0;
- while (*p) {
- dlist = (char **) xrealloc(dlist, sizeof(*dlist) * (++i + 1));
- // fprintf(stderr, "Found: %d, %s\n", i, p);
- dlist[i-1] = xstrdup(p);
- dlist[i] = NULL;
- while (*p++);
- }
- }
-
- return dlist;
-}
-
/*
* Main entry point from the upper layer. Walk the device tree, find our
* device, and light it up.
if (!SetupDiEnumDeviceInterfaces(hdevinfo, NULL,
&GARMIN_GUID,
req_unit_number, &devinterface)) {
- // If there were zero matches, we may be trying to talk to a "GPX Mode" device.
-
-
- char** dlist = get_garmin_mountpoints();
- gdx = gdx_find_file(dlist);
- if (gdx) {
- return 1;
- }
-
-
- // Plan C.
GPS_Serial_Error("SetupDiEnumDeviceInterfaces");
warning("Is the Garmin USB unit number %d powered up and connected?\nIs it really a USB unit? If it's serial, don't choose USB, choose serial.\nAre the Garmin USB drivers installed and functioning with other programs?\nIs it a storage based device like Nuvi, CO, or OR?\n If so, send GPX files to it, don't use this module.\n", un);
return 0;